using System;
using System.Text;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Services.Cache
{
    /// <summary>
    /// Memcached 二进制协议辅助类
    /// 提供Memcached二进制协议的基础命令实现（仅包含set/get/delete操作）
    /// </summary>
    public static class MemcachedBinaryProtocolHelper
    {
        /// <summary>
        /// 请求魔数标识
        /// </summary>
        private const byte RequestMagic = 0x80;
        
        /// <summary>
        /// 响应魔数标识
        /// </summary>
        private const byte ResponseMagic = 0x81;
        
        /// <summary>
        /// 协议头长度（字节）
        /// </summary>
        private const int HeaderLength = 24;

        /// <summary>
        /// 构造SET命令包
        /// 创建符合Memcached二进制协议的SET操作数据包
        /// </summary>
        /// <param name="key">缓存键名</param>
        /// <param name="value">缓存值的字节数组</param>
        /// <param name="expire">过期时间（秒）</param>
        /// <returns>完整的SET命令数据包</returns>
        public static byte[] BuildSetPacket(string key, byte[] value, uint expire)
        {
            var keyBytes = Encoding.UTF8.GetBytes(key);
            var totalLength = HeaderLength + keyBytes.Length + value.Length + 8; // 8字节: flags(4)+expire(4)
            var packet = new byte[totalLength];
            packet[0] = RequestMagic;
            packet[1] = 0x01; // opcode: set
            packet[2] = (byte)((keyBytes.Length >> 8) & 0xFF);
            packet[3] = (byte)(keyBytes.Length & 0xFF);
            packet[4] = 8; // extras length
            // ...header填充...
            Array.Copy(BitConverter.GetBytes((uint)(keyBytes.Length + value.Length + 8)), 0, packet, 8, 4); // body length
            // extras: flags(4)+expire(4)
            Array.Copy(BitConverter.GetBytes((uint)0), 0, packet, HeaderLength, 4); // flags
            Array.Copy(BitConverter.GetBytes(expire), 0, packet, HeaderLength + 4, 4); // expire
            // key
            Array.Copy(keyBytes, 0, packet, HeaderLength + 8, keyBytes.Length);
            // value
            Array.Copy(value, 0, packet, HeaderLength + 8 + keyBytes.Length, value.Length);
            return packet;
        }

        /// <summary>
        /// 构造GET命令包
        /// 创建符合Memcached二进制协议的GET操作数据包
        /// </summary>
        /// <param name="key">要获取的缓存键名</param>
        /// <returns>完整的GET命令数据包</returns>
        public static byte[] BuildGetPacket(string key)
        {
            var keyBytes = Encoding.UTF8.GetBytes(key);
            var totalLength = HeaderLength + keyBytes.Length;
            var packet = new byte[totalLength];
            packet[0] = RequestMagic;
            packet[1] = 0x00; // opcode: get
            packet[2] = (byte)((keyBytes.Length >> 8) & 0xFF);
            packet[3] = (byte)(keyBytes.Length & 0xFF);
            packet[4] = 0; // extras length
            Array.Copy(BitConverter.GetBytes((uint)keyBytes.Length), 0, packet, 8, 4); // body length
            Array.Copy(keyBytes, 0, packet, HeaderLength, keyBytes.Length);
            return packet;
        }

        /// <summary>
        /// 构造DELETE命令包
        /// 创建符合Memcached二进制协议的DELETE操作数据包
        /// </summary>
        /// <param name="key">要删除的缓存键名</param>
        /// <returns>完整的DELETE命令数据包</returns>
        public static byte[] BuildDeletePacket(string key)
        {
            var keyBytes = Encoding.UTF8.GetBytes(key);
            var totalLength = HeaderLength + keyBytes.Length;
            var packet = new byte[totalLength];
            packet[0] = RequestMagic;
            packet[1] = 0x04; // opcode: delete
            packet[2] = (byte)((keyBytes.Length >> 8) & 0xFF);
            packet[3] = (byte)(keyBytes.Length & 0xFF);
            packet[4] = 0; // extras length
            Array.Copy(BitConverter.GetBytes((uint)keyBytes.Length), 0, packet, 8, 4); // body length
            Array.Copy(keyBytes, 0, packet, HeaderLength, keyBytes.Length);
            return packet;
        }

        /// <summary>
        /// 解析GET响应数据包
        /// 从Memcached二进制协议GET响应中提取缓存值的字节数组
        /// </summary>
        /// <param name="response">GET操作的响应数据包</param>
        /// <returns>缓存值的字节数组，如果解析失败或数据不存在则返回null</returns>
        public static byte[]? ParseGetResponse(byte[] response)
        {
            if (response.Length < HeaderLength) return null;
            if (response[0] != ResponseMagic || response[1] != 0x00) return null;
            var extrasLen = response[4];
            var keyLen = (response[2] << 8) | response[3];
            var bodyLen = BitConverter.ToInt32(response, 8);
            if (bodyLen <= extrasLen + keyLen) return null;
            var valueLen = bodyLen - extrasLen - keyLen;
            var valueOffset = HeaderLength + extrasLen + keyLen;
            if (valueOffset + valueLen > response.Length) return null;
            var value = new byte[valueLen];
            Array.Copy(response, valueOffset, value, 0, valueLen);
            return value;
        }
    }
}
